﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Xml;
using System.IO;


namespace Parallel3M.parallel3m.framework
{
    public class ParallelApplicationConfigParser
    {
        public ParallelApplication application;
        public ArrayList elements=new ArrayList();
        public ArrayList connections = new ArrayList();
        public Hashtable applicationAttributes = new Hashtable();

        public void Parser(String configXml)
        {

            // Create an XmlReader
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(configXml);
            XmlNodeList nodes = doc.ChildNodes;

            XmlNode appNode = nodes[0];
            XmlAttributeCollection atts = appNode.Attributes;

            foreach (XmlAttribute att in atts)
            {
                applicationAttributes.Add(att.Name, att.Value);
            }

            XmlNodeList childs = appNode.ChildNodes;
            foreach (XmlNode node in childs)
            {
                String nodeName = node.Name;
                XmlAttributeCollection nodeatts = node.Attributes;
                Hashtable node_att = new Hashtable();
                foreach (XmlAttribute att in nodeatts)
                {
                    node_att.Add(att.Name, att.Value);
                }
                node_att.Add("xmlNode", node);
                node_att.Add("elem", nodeName);
                if (nodeName == "ParallelConnection")
                {
                    connections.Add(node_att);
                }
                else
                {                    
                    elements.Add(node_att);

                }
            }

            //inital application attributes
            application.name = (String) applicationAttributes["name"];

            //application.pcsid = (String)applicationAttributes["pcsid"];

            application.pcsid = Guid.NewGuid().ToString();

            //generate the objects
            foreach (Hashtable element in elements)
            {
                String elem_type = (String)element["elem"];
                XmlNode node = (XmlNode)element["xmlNode"];
                if (elem_type == "ParallelChannel")
                {
                    ParallelChannel channel = new ParallelChannel();                    
                    channel.node = node;
                    channel.PreParse();
                    application.elements.Add(channel.name, channel);
                }
                else if (elem_type == "ParallelProcessor")
                {
                    String process_type = (String)element["type"];
                    ParallelProcessor parallelProcessor = (ParallelProcessor) Activator.CreateInstance(null, process_type).Unwrap();
                    if (parallelProcessor != null)
                    {
                        parallelProcessor.application = application;
                        parallelProcessor.node = node;
                        parallelProcessor.PreParse();                        
                        application.addParallelElement(parallelProcessor);
                     }
                   

                }
            }

            foreach (Hashtable connectionAtt in connections)
            {
                ParallelConnection connection = new ParallelConnection();
                connection.name = (String)connectionAtt["name"];
                String from = (String)connectionAtt["from"];
                String to = (String)connectionAtt["to"];

                ParallelElement fromElement = (ParallelElement)application.elements[from];
                ParallelElement toElement = (ParallelElement)application.elements[to];
                connection.from = fromElement;
                connection.to = toElement;

                fromElement.outputConnections.Add(connection);
                toElement.inputConnections.Add(connection);

                application.addParallelConnection(connection);


            }

            foreach (DictionaryEntry processorPair in application.elements)
            {
                ParallelElement processor = (ParallelElement)processorPair.Value;
                processor.PostParse();
            }

            String userSingleChannel = (string)applicationAttributes["userSingleTaskChannel"];
            application.userSingleTaskChannel = (ParallelChannel) application.elements[userSingleChannel];

            String userGraphChannel = (string)applicationAttributes["userGraphTaskChannel"];
            if (userGraphChannel != null)
            {
                application.userGraphTaskChannel = (ParallelChannel)application.elements[userGraphChannel];
            }

            String userCompletedSinker = (string)applicationAttributes["userCompletedSinker"];
            if (userCompletedSinker != null)
            {
                application.userCompletedSinker = (ParallelSinker)application.elements[userCompletedSinker];
            }

        }

    }
}
